import './style.css'
import {gsap} from 'gsap'
import {Rendering} from './rendering'
import * as THREE from 'three'

import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
// import {glsl} from 'three/nodes'
import vertexShader from './glsl/vertexShader.glsl?raw'
import fragmentShader from './glsl/fragmentShader.glsl?raw'
import {GeometryUtil, MeshUtil} from './geometry_utils'

class Demo {
  constructor(particle_count = 800, particle_size = 0.1,
              particle_colors = ['#FFD542', '#FF4141', '#B75AFF', '#ffc0cb', '#0000ff']) {
    // 粒子数量
    this.particle_count = particle_count
    // 粒子大小
    this.particle_size = particle_size
    // 粒子颜色
    this.particle_colors = particle_colors

    this.rendering = new Rendering(document.querySelector('#canvas'))
    this.rendering.camera.position.z = 15
    this.controls = new OrbitControls(this.rendering.camera, this.rendering.canvas)

    this.uTime = new THREE.Uniform(0)
    this.init()
  }
  // 初始化灯光
  initLight() {
    let ambient = new THREE.AmbientLight(0xffffff, .75)
    let sun = new THREE.DirectionalLight(0xffffff, 2.0)
    sun.position.set(0.5, 0.5, 0.5)

    this.rendering.scene.add(sun)
    this.rendering.scene.add(ambient)
  }

  initMaterial() {
    this.mat = new THREE.MeshPhysicalMaterial({
      color: 0x202020,
      metalness: 0.4,
      roughness: 0.
    })

    let uniforms = {
      uTime: this.uTime,
      uColors: {value: this.particle_colors.map(c => new THREE.Color(c))}
    }
    this.mat.onBeforeCompile = (shader) => {
      shader.vertexShader = vertexShader
      shader.fragmentShader = fragmentShader
      shader.uniforms = {
        ...shader.uniforms,
        ...uniforms
      }
    }
  }

  initParentObject3D() {

    const count = Math.floor(this.particle_count / 2)
    const size = this.particle_size

    let parent = new THREE.Object3D()
    parent.position.y += 4
    // parent.add(MeshUtil.create(GeometryUtil.cone(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.capsule(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.box(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.torus(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.cylinder(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.dodecahedron(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.icosahedron(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.lathe(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.lathe(size, 2),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.lathe(size, 3),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.lathe(size, 4),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.lathe(size, 5),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.octahedron(size),this.mat, count))
    parent.add(MeshUtil.create(GeometryUtil.heart(size),this.mat, count))
    // parent.add(MeshUtil.create(GeometryUtil.torus_knot(size),this.mat, count))
    this.rendering.scene.add(parent)
  }

  init() {
    // 初始化灯光
    this.initLight()
    // 材质
    this.initMaterial()
    // 网格
    this.initParentObject3D()
    this.addEvents()
  }

  addEvents() {
    gsap.ticker.add(this.tick)
  }

  tick = (time, delta) => {
    this.uTime.value += delta * 0.001 * 0.5
    this.rendering.render()
  }
}

let demo = new Demo()

